package com.test.strategy;

import com.test.definition.BeanDefinition;
import com.test.exception.BeansException;

import java.lang.reflect.Constructor;

/**
 * 简单的实例化策略类，实现了InstantiationStrategy接口
 * 该策略主要负责根据BeanDefinition中定义的信息来实例化bean
 */
public class SimpleInstantiationStrategy implements InstantiationStrategy{
    /**
     * 实例化bean的方法
     *
     * @param beanDefinition Bean的定义信息，包含bean类的Class对象和其他元数据
     * @param beanName       Bean的名称，用于错误信息中
     * @param ctor           构造函数，如果提供了构造函数，则使用该构造函数实例化bean
     * @param args           构造函数的参数，如果构造函数不为空，则需要提供相应的参数
     * @return 实例化的bean对象
     * @throws BeansException 如果实例化bean过程中出现异常，则抛出该异常
     */
    @Override
    public Object instantiate(BeanDefinition beanDefinition, String beanName, Constructor<?> ctor, Object[] args) {
        // 获取BeanDefinition中定义的类
        Class<?> clazz = beanDefinition.getBeanClass();
        try {
            // 如果提供了构造函数
            if (ctor != null) {
                // 确保参数数组不为空
                if (args == null){
                    args = new Object[0];
                }
                // 检查构造函数参数个数是否匹配
                if (args.length != ctor.getParameterCount()){
                    throw new RuntimeException("构造函数参数个数不匹配： " + beanName +
                            ", 期望" + ctor.getParameterCount() + "个， 实际" + args.length);
                }
                // 使用提供的构造函数和参数实例化bean
                return ctor.newInstance(args);
            }else {
                // 如果没有提供构造函数，则使用无参构造函数实例化bean
                return clazz.getDeclaredConstructor().newInstance();
            }

        } catch (Exception e) {
            // 如果实例化过程中出现异常，抛出自定义的BeansException异常
            throw new BeansException("实例化bean失败 [" + beanName + "]", e);
        }
    }
}
